﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using EstateNuke.Data.Properties;

namespace EstateNuke.Data
{
    public partial class User
    {
        #region Fileds & Properties

        /// <summary>
        /// </summary>
        public string DisplayName
        {
            get
            {
                return string.Format("{0}-{1}{2}", UserName, Name, IsDeleted ? " (已删除)" : "");
            }
        }

        /// <summary>
        /// </summary>
        internal IList<ProjectUser> ProjectUsers
        {
            get
            {
                return InternalProjectUsers.Where(projectUser => projectUser.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IList<Project> Projects
        {
            get
            {
                return InternalProjectUsers.Where(projectUser => projectUser.IsDeleted == false && projectUser.Project.IsDeleted == false).Select(projectUser => projectUser.Project).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IList<Plan> Plans
        {
            get
            {
                return InternalPlans.Where(plan => plan.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IList<Report> Reports
        {
            get
            {
                return InternalReports.Where(report => report.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IList<ReportReply> ReportReplies
        {
            get
            {
                return InternalReportReplies.Where(reportReply => reportReply.IsDeleted == false).ToList();
            }
        }

        #endregion

        #region Add & Remove Plan

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Plan AddDailyPlan(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var plan = new Plan
                           {
                               RowId = Guid.NewGuid(),
                               CreatedDate = DateTime.Now,
                           };
            InternalPlans.Add(plan);
            plan.IsDeleted = false;
            plan.ModifiedDate = DateTime.Now;
            plan.ModifiedByUser = modifiedUser;
            plan.BeginDate = DateTime.Now.Date.AddDays(1);
            plan.EndDate = DateTime.Now.Date.AddDays(1);
            return plan;
        }

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Plan AddWeeklyPlan(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var plan = new Plan
                           {
                               RowId = Guid.NewGuid(),
                               CreatedDate = DateTime.Now,
                           };
            InternalPlans.Add(plan);
            plan.IsDeleted = false;
            plan.ModifiedDate = DateTime.Now;
            plan.ModifiedByUser = modifiedUser;
            plan.BeginDate = DateTime.Now.Date.AddDays(-(int) DateTime.Now.DayOfWeek).AddDays(7);
            plan.EndDate = plan.BeginDate.AddDays(7);
            return plan;
        }

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Plan AddMonthlyPlan(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var plan = new Plan
                           {
                               RowId = Guid.NewGuid(),
                               CreatedDate = DateTime.Now,
                           };
            InternalPlans.Add(plan);
            plan.IsDeleted = false;
            plan.ModifiedDate = DateTime.Now;
            plan.ModifiedByUser = modifiedUser;
            plan.BeginDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1);
            plan.EndDate = plan.BeginDate.AddMonths(1);
            return plan;
        }

        /// <summary>
        /// </summary>
        /// <param name = "plan"></param>
        /// <param name = "modifiedUser"></param>
        public void RemovePlan(Plan plan, User modifiedUser)
        {
            if (plan == null)
            {
                throw new ArgumentNullException("plan");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalPlans.Contains(plan))
            {
                plan.Delete(modifiedUser);
            }
        }

        #endregion

        #region Add & Remove Report

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Report AddDailyReport(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var report = new Report
                             {
                                 RowId = Guid.NewGuid(),
                                 CreatedDate = DateTime.Now,
                             };
            InternalReports.Add(report);
            report.IsDeleted = false;
            report.ModifiedDate = DateTime.Now;
            report.ModifiedByUser = modifiedUser;
            report.ReportTypeId = 1;
            report.BeginDate = DateTime.Now.Date;
            report.EndDate = DateTime.Now.Date.AddDays(1);
            return report;
        }

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Report AddWeeklyReport(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var report = new Report
                             {
                                 RowId = Guid.NewGuid(),
                                 CreatedDate = DateTime.Now,
                             };
            InternalReports.Add(report);
            report.IsDeleted = false;
            report.ModifiedDate = DateTime.Now;
            report.ModifiedByUser = modifiedUser;
            report.ReportTypeId = 2;
            report.BeginDate = DateTime.Now.Date.AddDays(-(int) DateTime.Now.DayOfWeek);
            report.EndDate = report.BeginDate.AddDays(7);
            return report;
        }

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public Report AddMonthlyReport(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var report = new Report
                             {
                                 RowId = Guid.NewGuid(),
                                 CreatedDate = DateTime.Now,
                             };
            InternalReports.Add(report);
            report.IsDeleted = false;
            report.ModifiedDate = DateTime.Now;
            report.ModifiedByUser = modifiedUser;
            report.ReportTypeId = 3;
            report.BeginDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            report.EndDate = report.BeginDate.AddMonths(1);
            return report;
        }

        /// <summary>
        /// </summary>
        /// <param name = "report"></param>
        /// <param name = "modifiedUser"></param>
        public void RemoveReport(Report report, User modifiedUser)
        {
            if (report == null)
            {
                throw new ArgumentNullException("report");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalReports.Contains(report))
            {
                report.Delete(modifiedUser);
            }
        }

        #endregion

        #region Add & Remove ProjectUser

        /// <summary>
        /// </summary>
        /// <returns></returns>
        internal ProjectUser AddProjectUser(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var projectUser = new ProjectUser
                                  {
                                      RowId = Guid.NewGuid(),
                                      CreatedDate = DateTime.Now,
                                  };
            InternalProjectUsers.Add(projectUser);
            projectUser.IsDeleted = false;
            projectUser.ModifiedDate = DateTime.Now;
            projectUser.ModifiedByUser = modifiedUser;
            return projectUser;
        }

        /// <summary>
        /// </summary>
        /// <param name = "projectUser"></param>
        /// <param name = "modifiedUser"></param>
        internal void RemoveProjectUser(ProjectUser projectUser, User modifiedUser)
        {
            if (projectUser == null)
            {
                throw new ArgumentNullException("projectUser");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalProjectUsers.Contains(projectUser))
            {
                projectUser.Delete(modifiedUser);
            }
        }

        #endregion

        #region Set Projects

        /// <summary>
        /// </summary>
        /// <param name = "projects"></param>
        /// <param name = "modifiedUser"></param>
        public void SetProjects(IList<Project> projects, User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (projects != null)
            {
                var projectUsers = InternalProjectUsers.ToList();
                projectUsers.ForEach(projectUser => projectUser.Delete(modifiedUser));
                foreach (var project in projects.Distinct())
                {
                    var currentProjectUser = projectUsers.FirstOrDefault(projectUser => projectUser.Project == project);
                    if (currentProjectUser != null)
                    {
                        currentProjectUser.CancelDelete(modifiedUser);
                    }
                    else
                    {
                        currentProjectUser = AddProjectUser(modifiedUser);
                        currentProjectUser.Project = project;
                    }
                }
            }
        }

        #endregion

        #region Ensure

        /// <summary>
        /// </summary>
        public void Ensure()
        {
            if (string.IsNullOrEmpty(UserName))
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NotNullAllowed, RowId, "User", "UserName"));
            }
            if (string.IsNullOrEmpty(Name))
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NotNullAllowed, RowId, "User", "Name"));
            }
            if (string.IsNullOrEmpty(Password))
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NotNullAllowed, RowId, "User", "Password"));
            }
            UserName = UserName.Length > 256 ? UserName.Substring(0, 256) : UserName;
            Name = Name.Length > 64 ? Name.Substring(0, 64) : Name;
            Mobile = string.IsNullOrEmpty(Mobile) ? null : Mobile.Length > 16 ? Mobile.Substring(0, 16) : Mobile;
            Email = string.IsNullOrEmpty(Email) ? null : Email.Length > 256 ? Email.Substring(0, 256) : Email;
            PasswordQuestion = string.IsNullOrEmpty(PasswordQuestion) ? null : PasswordQuestion.Length > 256 ? PasswordQuestion.Substring(0, 256) : PasswordQuestion;
            PasswordAnswer = string.IsNullOrEmpty(PasswordAnswer) ? null : PasswordAnswer.Length > 128 ? PasswordAnswer.Substring(0, 128) : PasswordAnswer;
            Comment = string.IsNullOrEmpty(Comment) ? null : Comment.Length > 512 ? Comment.Substring(0, 512) : Comment;
        }

        #endregion

        #region Delete

        /// <summary>
        /// </summary>
        public void Delete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = true;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            ((List<Plan>) Plans).ForEach(plan => plan.Delete(modifiedUser));
            ((List<Report>) Reports).ForEach(report => report.Delete(modifiedUser));
            ((List<ProjectUser>) ProjectUsers).ForEach(projectUser => projectUser.Delete(modifiedUser));
        }

        /// <summary>
        /// </summary>
        public void CancelDelete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = false;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
        }

        #endregion
    }
}